package main

import (
	"fmt"
	"github.com/hashicorp/consul/api"
	"github.com/satori/go.uuid"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"os"
	"os/signal"
	"strconv"
	"syscall"
	"web/goods/global"
	"web/goods/initialize"
	"web/goods/proto"
	"web/goods/utils"
)

func main() {
	// 1. 初始化logger
	initialize.InitLogger()

	// 2. 初始化配置信息
	initialize.InnitConfig()

	// 3. 初始化routers
	r := initialize.Routers()

	// 4. 初始化通用翻译器
	if err := initialize.InitTrans("zh"); err != nil {
		zap.S().Panic("初始化通用翻译器失败:", err)
		return
	}

	// 5. 初始化service层服务的连接
	// 商品服务
	if conn := initialize.InitSrvConn(global.ServerConfig.GoodsSrvInfo.Name); conn != nil {
		global.GoodsSrvClient = proto.NewGoodsClient(conn)
	}
	// 用户服务
	if conn := initialize.InitSrvConn(global.ServerConfig.UserSrvInfo.Name); conn != nil {
		global.UserSrvClient = proto.NewUserClient(conn)
	}
	// 库存服务
	if conn := initialize.InitSrvConn(global.ServerConfig.InventorySrvInfo.Name); conn != nil {
		global.InventorySrvClient = proto.NewInventoryClient(conn)
	}

	// 6. 初始化sentinel，用于限流
	initialize.InitSentinel()

	// 如果是本地开发环境，则服务启动端口号固定，从配置文件中获取，
	// 如果是线上环境，则动态获取可用端口号
	viper.AutomaticEnv()
	debug := viper.GetBool("YGSHOP_DEBUG")
	if !debug {
		port, err := utils.GetAvailablePort()
		if err == nil {
			global.ServerConfig.Port = port
		}
	}

	zap.L().Debug("启动服务器", zap.Int("端口", global.ServerConfig.Port))

	// 将当前web服务注册到consul
	serviceId := uuid.NewV4().String()
	client, err := Register(global.ServerConfig.Host, global.ServerConfig.Name, serviceId,
		global.ServerConfig.Port, global.ServerConfig.Tags)
	if err != nil {
		panic(err)
	}

	go func() {
		if err := r.Run(":" + strconv.Itoa(global.ServerConfig.Port)); err != nil {
			zap.L().Panic("启动失败", zap.String("具体原因", err.Error()))
		}
	}()

	// 接收终止信号
	quit := make(chan os.Signal)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	if err = client.Agent().ServiceDeregister(serviceId); err != nil {
		zap.S().Error("服务注销失败")
	}
	zap.S().Info("服务注销成功")
}

func Register(address, name, id string, port int, tags []string) (*api.Client, error) {
	cfg := api.DefaultConfig()
	// 设置consul服务运行所在的ip和端口
	//cfg.Address = "10.58.85.159:8500"
	//cfg.Address的ip可以是127.0.0.1

	client, err := api.NewClient(cfg)
	if err != nil {
		panic(err)
	}

	// 生成健康检查对象
	check := &api.AgentServiceCheck{
		// 这里的ip不可以是127.0.0.1
		HTTP:                           fmt.Sprintf("http://%s:%d/health", address, port), // user-web服务的运行地址
		Timeout:                        "5s",                                              // 超过此时间说明服务状态不健康
		Interval:                       "5s",                                              // 每5s检查一次
		DeregisterCriticalServiceAfter: "30s",                                             // 失败多久后注销服务
	}

	// 生成注册对象
	registration := &api.AgentServiceRegistration{
		Name:    name,
		ID:      id,
		Address: address,
		Port:    port,
		Tags:    tags,
		Check:   check,
	}

	// 注册服务
	return client, client.Agent().ServiceRegister(registration)
}
